home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d1 / adjram31.arc / AMDISK31.ASM < prev    next >
Assembly Source File  |  1986-10-02  |  21KB  |  674 lines

  1. ; ==== Adjustable Memory Disk Device Driver ====
  2. ;
  3. ; (c) Copyright 1986 by Gary R. Cramblitt
  4. ;
  5. ; v2.2  1 Jul 86  Initial version
  6. ; v2.3 24 Aug 86  Bug.  FAT media byte not updated properly
  7. ; v2.4 29 Aug 86  Sync version # with ADJRAM.C  No other changes.
  8. ; v2.5 30 Aug 86  Add /E (LOTUS/INTEL,Microsoft Expanded Memory) support;
  9. ;          Increase root directory to 128 entries;
  10. ;          Permit maximum size of 2043K.
  11. ;          Get rid of second FAT.
  12. ; v3.0  5 Sep 86  Sync version # with ADJRAM.C.  No other changes.
  13. ; v3.1  2 Oct 86  Sync version # with ADJRAM.C.  No other changes.
  14. ;
  15. ; ==== Constant Definition ===================
  16. ;
  17. ; ---- Customizable Definitions -----
  18. ;      If these are changed, the corresponding symbols in adjram.c
  19. ;      must be altered.
  20.  
  21. min_size_K    equ    64        ; minimum 64K ram disk
  22. max_size_K    equ    2043        ; maximum 2043K ram disk
  23. sec_per_blk    equ    64        ; 32K increments
  24. bytes_per_sec    equ    512        ; bytes per sector
  25. sec_per_cl    equ    1        ; sectors per cluster
  26. par_per_sec_lg2    equ    5        ; 16-byte paragraphs per sector
  27.                     ;   log 2.  Must match bytes_per_sec
  28. fats_per_disk    equ    1        ; number of FATS
  29.  
  30. ; ---- Derived quantities ----
  31.  
  32. sec_per_K    equ    1024/bytes_per_sec ; sectors per 1024 bytes
  33. par_per_sec    equ    bytes_per_sec/16   ; 16-byte paragraphs per sector
  34. min_size_sec    equ    min_size_K*sec_per_K ; min size of disk in sectors
  35. max_size_sec    equ    max_size_K*sec_per_K ; max size of disk in sectors
  36. bytes_per_fat    equ    max_size_sec/sec_per_cl*3/2
  37. sec_per_fat    equ    (bytes_per_fat+bytes_per_sec-1)/bytes_per_sec
  38. K_per_blk    equ    sec_per_blk/sec_per_K
  39. em_pag_per_mem_blk equ    K_per_blk/16    ; EM pages per memory block
  40.  
  41. ; ---- Request Header Structure Definitions ----
  42.  
  43. rh_length    equ    0        ; (byte) length field
  44. rh_unit        equ    1 + rh_length    ; (byte) unit field
  45. rh_command    equ    1 + rh_unit    ; (byte) command code
  46. rh_status    equ    1 + rh_command    ; (word) status field
  47. rh_reserved    equ    2 + rh_status    ; (8 bytes)
  48. rh_size        equ    8 + rh_reserved    ; request header size
  49.  
  50. ; ---- Request Header Status values ----
  51.  
  52. s_done        equ    0100h    ; done, no errors
  53. s_busy        equ    0200h    ; busy, no errors
  54.  
  55. e_err        equ    8000h
  56. e_protect    equ    e_err+0h    ; error: write protect
  57. e_unknown_unit    equ    e_err+1h    ; error: unknown unit
  58. e_not_ready    equ    e_err+2h    ; error: not ready
  59. e_command    equ    e_err+3h    ; error: unknown command
  60. e_crc        equ    e_err+4h    ; error: bad CRC
  61. e_bad_length    equ    e_err+5h    ; error: bad structure length
  62. e_seek        equ    e_err+6h    ; error: bad seek
  63. e_media        equ    e_err+7h    ; error: unknown media
  64. e_not_found    equ    e_err+8h    ; error: sector not found
  65. e_paper        equ    e_err+9h    ; error: out of paper
  66. e_write        equ    e_err+ah    ; error: write fault
  67. e_read        equ    e_err+bh    ; error: read fault
  68. e_general    equ    e_err+ch    ; error: general error not listed above
  69.  
  70. ; ---- Non-destructive read parameter block ----
  71.  
  72. rh_read_data    equ    rh_size    ; (byte) non-destructive data
  73.  
  74. ; ---- Input/output parameter block ----
  75.  
  76. rh_media    equ    0 + rh_size        ; (byte) media descriptor
  77. rh_buf_offset    equ    1 + rh_media        ; (word) transfer buffer offset
  78. rh_buf_segment    equ    2 + rh_buf_offset    ; (word) transfer buffer segment
  79. rh_buf_size    equ    2 + rh_buf_segment    ; (word) transfer buffer size
  80. rh_start    equ    2 + rh_buf_size        ; (word) transfer starting sector
  81.  
  82. m_fized        equ    0f8h    ; media: fixed disk
  83.  
  84. m_ss9        equ    0fch    ; media: single sided, 8 sectors/track
  85. m_ds9        equ    0fdh
  86. m_ss8        equ    0feh
  87. m_ds8        equ    0ffh
  88.  
  89. ; ---- Build BPB parameter block ----
  90.                         ; preceeded by media descriptor
  91. rh_bpb        equ    1 + rh_media        ; (dword) bpb buffer address
  92. rh_tbl_offset    equ    4 + rh_bpb        ; (dword) bpb table offset/segment
  93. rh_tbl_segment    equ    2 + rh_tbl_offset
  94.  
  95. ; ---- Media Check parameter block ----
  96.  
  97. rh_check    equ    1 + rh_media        ; (byte) media check result
  98.  
  99. mc_changed    equ    -1            ; media has changed
  100. mc_maybe    equ    0            ; media may have been changed
  101. mc_same        equ    1            ; media has not changed
  102.  
  103. ; ---- Initialize parameter block ----
  104.  
  105. rh_units    equ    0 + rh_size        ; (byte) number of units supported
  106. rh_end_offset    equ    1 + rh_units        ; (word) end address of driver
  107. rh_end_segment    equ    2 + rh_end_offset
  108. rh_bpb_offset    equ    2 + rh_end_segment    ; (word) BPB array address
  109. rh_bpb_segment    equ    2 + rh_bpb_offset
  110.  
  111. ; ---- DOS interrupts ----
  112.  
  113. dosi_dosf    equ    21h        ; DOS function dispatcher
  114.  
  115. ; ---- User Interrupts ----
  116.  
  117. usri_emm    equ    67h        ; Expanded Memory Manager
  118.  
  119. ; ---- DOS interrupt 21 functions ----
  120.  
  121. dosf_outstr    equ    9        ; display string
  122. dosf_seldisk    equ    0eh        ; select disk
  123. dosf_getdisk    equ    19h        ; get current disk
  124.  
  125. ; ---- LOTUS/INTEL/Microsoft Expanded Memory Manager functions ----
  126.  
  127. emm_status    equ    40h        ; get manager status
  128. emm_get_PFseg    equ    41h        ; get page frame segment
  129. emm_get_pages    equ    42h        ; get number of pages
  130. emm_get_handle    equ    43h        ; get handle and allocate memory
  131. emm_map_memory    equ    44h        ; map memory
  132. emm_fre_handle    equ    45h        ; free handle and memory
  133. emm_get_ver    equ    46h        ; get EMM version
  134. emm_sav_map    equ    47h        ; save mapping context
  135. emm_res_map    equ    48h        ; restore mapping context
  136. emm_num_handles    equ    4bh        ; get number of EMM handles
  137. emm_hdl_pages    equ    4ch        ; get pages owned by handle
  138. emm_all_pages    equ    4dh        ; get pages for all handles
  139. emm_pag_map    equ    4eh        ; get or set page map
  140.  
  141. ; ---- Device Driver Header Attribute Definitions ----
  142.  
  143. a_input        equ    0001h        ; standard input device
  144. a_output    equ    0002h        ; standard output device
  145. a_nul        equ    0004h        ; NUL device
  146. a_clock        equ    0008h        ; CLOCK$ device
  147. a_dos        equ    0        ; DOS block device (bit 13)
  148. a_not_dos    equ    2000h        ; non-DOS block device (bit 13)
  149. a_ioctl        equ    4000h        ; IOCTL functions supported
  150. a_block        equ    0        ; block device (bit 15)
  151. a_character    equ    8000h        ; character device (bit 15)
  152.  
  153. ; ==== Device Driver Header Definition ====
  154.  
  155. cseg    segment para public 'CODE'
  156.  
  157. driver    proc far
  158.  
  159.     assume cs:cseg,ds:cseg,es:cseg
  160.  
  161.     dd    -1            ; last driver in chain
  162.     dw    a_block + a_dos        ; driver attribute
  163.     dw    dev_strategy        ; offset to strategy routine
  164.     dw    dev_interrupt        ; offset to interrupt routine
  165.     db    1            ; number of devices or device name
  166.     db    7 dup ( ? )        ; filler for block device
  167.  
  168. ; ==== Device Driver Tables ====
  169. ;
  170. ; ---- BIOS Parameter Block Table and Entries ----
  171.  
  172. bpb_table    dw    bpb        ; one entry for each unit
  173.  
  174. ; ---- Request Header Address set by dev_strategy ----
  175.  
  176. rh_address    dd    1 dup ( ? )        ; request header base address
  177.  
  178. rh_offset    equ    word ptr rh_address
  179. rh_segment    equ    word ptr rh_address + 2
  180.  
  181. ; ---- Request Header Command Dispatch Table ----
  182.  
  183. cmd_table    dw    initialize    ; initialize driver
  184.         dw    media_check    ; media check
  185.         dw    build_bpb    ; build BPB
  186.         dw    ioctl_read    ; IOCTL read
  187.         dw    read        ; normal read
  188.         dw    check_input    ; non-destructive read/status
  189.         dw    input_status    ; input status
  190.         dw    input_flush    ; flush input buffers
  191.         dw    write        ; normal write
  192.         dw    write_verify    ; normal write with read verify
  193.         dw    output_status    ; output status
  194.         dw    output_flush    ; flush output buffer
  195.         dw    ioctl_write    ; IOCTL write
  196.  
  197. ; ==== Common Device Driver Routines ====
  198. ;
  199. ; ---- Device Driver Strategy Routine ----
  200. ;
  201. ; es:bs == request header address
  202.  
  203. dev_strategy    proc    far
  204.         mov    cs:rh_offset,bx
  205.         mov    cs:rh_segment,es
  206.         ret
  207. dev_strategy    endp
  208.  
  209. ; ---- Device Driver Interrupt Routine ----
  210.  
  211. dev_interrupt    proc    far
  212.         push    ax            ; save registers used
  213.         push    bx
  214.         push     cx
  215.         push    dx
  216.         push    di
  217.         push    si
  218.         push    ds
  219.         push    es
  220.          cld                ; clear direction flag
  221.          push    cs            ; setup small memory model
  222.          pop    ds            ; ds := program segment
  223.          les    bx,rh_address        ; es:bs := request header index
  224.          mov    si,es:rh_command[bx]    ; si := request command (byte)
  225.          and    si,0ffh            ; si := request command
  226.          add    si,si            ; si := word table offset
  227.          call    word ptr cmd_table[si]    ; ax := command result
  228.          lds    bx,cs:rh_address    ; ds:bx := request header index
  229.          mov    rh_status[bx],ax    ; update request status
  230.         pop    es            ; restore register
  231.         pop    ds
  232.         pop    si
  233.         pop    di
  234.         pop    dx
  235.         pop    cx
  236.         pop    bx
  237.         pop    ax
  238.         ret
  239.  
  240. dev_interrupt    endp
  241.  
  242. ; **** END OF DEVICE INDEPENDENT PORTION OF DRIVER ****
  243.  
  244. ; ---- Memory Block Table that follows BPB in boot sector ----
  245.  
  246. mem_blk_table_entry    struc
  247. typ        db    ?        ; 0 = normal  1 = Expanded Memory
  248. par        dw    ?        ; paragraph address of block
  249. siz        dw    ?        ; number of sectors in the memory block
  250. hdl        dw    ?        ; EM handle for the block
  251. mem_blk_table_entry    ends
  252.  
  253. nor_flg        equ    0        ; Memory Block is in normal memory
  254. em_flg        equ    1        ; Memory Block is in expanded memory
  255.  
  256. ; ---- Flag indicating whether expanded memory mapping context has been
  257. ;      saved yet or not.  If nonzero, it indicates that the context has
  258. ;      been saved.
  259.  
  260. em_context_flg    db    0        ; 0 = not saved; 1 = context saved
  261. em_context_hdl    dw    ?        ; EM handle underwhich context saved
  262.  
  263. ; ==== Memory Disk Device Driver Code ====
  264. ;
  265. ; ---- Driver support functions (near functions) ----
  266. ;
  267. ; es:bx == request header
  268. ; ds    == cs
  269. ; All other registers are usable.
  270. ;
  271. ; ax := result status
  272. ;
  273. ; ---- Initialize driver ----
  274.  
  275. initialize    proc    near        ; initialize driver
  276.  
  277.     lea    ax,word ptr mdisk_data    ; ax := end of driver
  278.     mov    cl,4            ; cl := paragraph size log2
  279.     shr    ax,cl            ; ax := paragraphs in driver
  280.     mov    dx,cs            ; dx := driver segment
  281.     add    ax,dx            ; ax := memory disk segment
  282.     mov    mem_blk_table.par,ax    ; update for subsequent transfers
  283.  
  284.     mov    ax,cs
  285.     mov    es,ax
  286.     lea    di,word ptr fat1    ; es:di := first FAT
  287.     mov    cx,sec_per_fat*bytes_per_sec ; cx = size
  288.     push    di            ; save first FAT address
  289.     push    es
  290.  
  291.      mov    al,cs:bpb_media        ; al := media byte
  292.      mov    [di],al            ; update FAT media byte
  293.      mov    word ptr 1[di],0ffffh    ; allocate initial sectors
  294.      add    di,3            ; adjust FAT index
  295.      sub    cx,3            ; adjust FAT size
  296.      xor    al,al            ; al := 0
  297.      rep    stosb            ; clear rest of FAT
  298.  
  299.     pop    ds
  300.     pop    si            ; ds:si := first FAT index
  301.  
  302.     if    fats_per_disk - 1    ; assemble if 2 FATS
  303.       lea    di,word ptr fat2    ; es:di := second FAT
  304.           mov    cx,sec_per_fat*bytes_per_sec ; cx := size
  305.       rep    movsb            ; copy first FAT to second FAT
  306.     endif
  307.  
  308.     mov    ax,cs:bpb_root        ; ax := number of directory entries
  309.     mov    cl,5            ; cl := size of entry log2 (32 bytes)
  310.     shl    ax,cl            ; ax := directory size
  311.  
  312.     mov    cx,ax            ; cx := directory size
  313.     xor    al,al            ; al := 0
  314.     rep    stosb            ; zero directory
  315.  
  316.     lds    bx,cs:rh_address    ; ds:bx := request header address
  317.     mov    byte ptr rh_units[bx],1    ; return number of units
  318.     mov    word ptr rh_end_offset[bx],offset mdisk_data
  319.     mov    rh_end_segment[bx],cs    ; Calc end address of disk
  320.     mov    ax,cs:mem_blk_table.siz
  321.     mov    cl,par_per_sec_lg2
  322.     shl    ax,cl
  323.     add    rh_end_segment[bx],ax    ; return ending address of driver
  324.     mov    word ptr rh_bpb_offset[bx],offset bpb_table
  325.     mov    rh_bpb_segment[bx],cs    ; return BPB table address
  326.  
  327.     push    cs
  328.     pop    ds
  329.     mov    ah,dosf_getdisk        ; get current default disk
  330.     int    dosi_dosf
  331.     mov    dl,al            ; select it 
  332.     mov    ah,dosf_seldisk
  333.     int    dosi_dosf        ; DL := number of drives
  334.     add    al,'A'            ; convert to letter
  335.     mov    drive,al        ; store into message
  336.     mov    dx,offset initok
  337.     mov    ah,dosf_outstr
  338.     int    dosi_dosf
  339.     mov    ax,s_done        ; ax := done, no errors
  340.     ret
  341.  
  342. initok    db    10,13,'AMDISK v3.1 (c) Copyright 1986 by Gary Cramblitt'
  343.     db    '-- Initialized as disk '
  344. drive    db    ' '
  345.     db    ':',10,13,'$'
  346.  
  347. initialize    endp
  348.  
  349. ; ---- Media check ----
  350. ;
  351. ; Memory disk is non-removable media, however, the size of the media
  352. ; can be changed.  We check the number of 64K memory blocks allocated,
  353. ; which is located in the boot record.  If it has changed, then the media
  354. ; has changed.
  355.  
  356. media_check    proc    near        ; media check
  357.  
  358.     lds    bx,cs:rh_address    ; ds:bx := request header address
  359.     mov    al,cs:bpb_media        ; Get our media byte
  360.     cmp    al,rh_media[bx]        ; Changed from what DOS has?
  361.     jz    media_same        ; -- Yes
  362.     mov    byte ptr rh_check[bx],mc_changed
  363.     mov    ax,s_done
  364.     ret
  365.  
  366. media_same:
  367.     mov    byte ptr rh_check[bx],mc_same
  368.     mov    ax,s_done        ; ax := function done, no errors
  369.     ret
  370.  
  371. media_check    endp
  372.  
  373. ; ---- Build BPB ----
  374. ;
  375. ; Read boot sector and copy into BPB buffer
  376. ; Adjust request header values
  377.  
  378. build_bpb    proc    near        ; build BPB
  379.  
  380.     mov    al,cs:bpb_media        ; al    := media byte
  381.     lds    bx,cs:rh_address    ; ds:bx    := request header address
  382.     mov    byte ptr rh_media[bx],al
  383.     mov    word ptr rh_tbl_offset[bx],offset bpb
  384.     mov    word ptr rh_tbl_segment[bx],cs
  385.     mov    ax,s_done        ; ax := function done, no errors
  386.      ret
  387.  
  388. build_bpb    endp
  389.  
  390. ; ---- Read from device ----
  391.  
  392. read        proc near        ; normal read
  393.  
  394.     push    es
  395.     pop    ds            ; ds := request header segment
  396.     mov    di,rh_buf_offset[bx]
  397.     mov    ax,di
  398.     and    di,000fh        ; di := buffer offset within paragraph
  399.     mov    cl,4
  400.     shr    ax,cl
  401.     add    ax,rh_buf_segment[bx]    ; ax := paragraph of buffer
  402.     mov    es,ax            ; es:di := normalized buffer address
  403.     mov    dx,rh_buf_size[bx]    ; dx := sectors to read
  404.     mov    ax,rh_start[bx]        ; ax := first sector to read
  405.  
  406.     mov    bx,-(size mem_blk_table_entry)    ; find the memory block which..
  407. find_mem_blk_2_read:                ;  contains the desired sector..
  408.     add    bx,size mem_blk_table        ; by subtracting the # of sectors..
  409.     sub    ax,cs:mem_blk_table.siz[bx] ; in each block.
  410.     jnc    find_mem_blk_2_read
  411.     add    ax,cs:mem_blk_table.siz[bx] ; bx := ptr to memory block table
  412.                         ; ax := sector within the block
  413.  
  414.     push    ax            ; save sector within block
  415.     mov    cl,par_per_sec_lg2    ; paragraphs per sector log 2
  416.     shl    ax,cl            ; ax := paragraph within memory block
  417.  
  418.     cmp    cs:mem_blk_table.typ[bx],em_flg ; Expanded Memory?
  419.     jnz    read_set_par
  420.     call    map_hdl_2_pages            ; - Yes, map EM to log mem
  421.  
  422. read_set_par:
  423.     add    ax,cs:mem_blk_table.par[bx] ; ax := paragraph in phy mem
  424.     mov    ds,ax
  425.     xor    si,si            ; ds:si := address of sector
  426.  
  427.     mov    cx,cs:mem_blk_table.siz[bx] ; cx := end sector
  428.     pop    ax            ; ax := start sector
  429.     sub    cx,ax            ; cx := secs remaining in mem blk
  430.  
  431. read_one_sector:
  432.     or    dx,dx            ; All sectors transfered?
  433.     jz    read_finish        ; -- Yes
  434.     dec    dx
  435.     push    cx            ; save sector count for this blk
  436.     mov    cx,bytes_per_sec    ; 512 bytes per sector
  437.     rep    movsb            ; copy sector to buffer
  438.     pop    cx            ; cx := secs remaining in this blk+1
  439.     mov    ax,ds
  440.     add    ax,par_per_sec        ; 32 paragraphs per sector
  441.     mov    ds,ax
  442.     xor    si,si            ; ds:si := address of next sector
  443.         mov    ax,es            ; advance es to next sector
  444.     add    ax,par_per_sec
  445.     mov    es,ax
  446.     and    di,000fh        ; es:di := normalized transfer address
  447.     loop    read_one_sector        ; if not end of mem blk, do another
  448.     add    bx,size mem_blk_table_entry
  449.  
  450.     cmp    cs:mem_blk_table.typ[bx],em_flg ; Expanded Memory?
  451.     jnz    read_set_par_in_loop
  452.     call    map_hdl_2_pages            ; - Yes, map EM to log mem
  453.  
  454. read_set_par_in_loop:
  455.     mov    ax,cs:mem_blk_table.par[bx]
  456.     mov    ds,ax            ; ds:si := start of new memory block
  457.     mov    cx,cs:mem_blk_table.siz[bx] ; cx := size of blk in sectors
  458.     jmp    read_one_sector
  459.  
  460. read_finish:
  461.     call    restore_em_context    ; If needed, restore em context
  462.     mov    ax,s_done        ; ax := transfer done
  463.     ret
  464.  
  465. read    endp
  466.  
  467. ; ---- Write to device ----
  468.  
  469. write        proc    near        ; normal write
  470.  
  471.     push    es
  472.     pop    ds            ; ds := request header segment
  473.     mov    dx,rh_buf_size[bx]    ; dx := sectors to write
  474.     mov    si,rh_buf_offset[bx]
  475.     mov    ax,si
  476.     and    si,000fh        ; si := buffer offset within paragraph
  477.     mov    cl,4
  478.     shr    ax,cl
  479.     add    ax,rh_buf_segment[bx]    ; ax := paragraph of buffer
  480.     mov    cx,ax
  481.     mov    ax,rh_start[bx]        ; ax := first sector to write
  482.     mov    ds,cx            ; ds:si := normalized buffer address
  483.  
  484.     mov    bx,-(size mem_blk_table_entry)    ; find the memory block which..
  485. find_mem_blk_2_write:                ;   contains the desired sector..
  486.     add    bx,size mem_blk_table_entry ;   by subtracting the # of sectors..
  487.     sub    ax,cs:mem_blk_table.siz[bx] ;  in each block.
  488.     jnc    find_mem_blk_2_write
  489.     add    ax,cs:mem_blk_table.siz[bx]
  490.                     ; bx := ptr to memory block table
  491.                     ; ax := sector within the block
  492.     push    ax            ; save sector within the block
  493.  
  494.     mov    cl,par_per_sec_lg2    ; 32 paragraphs per sector log 2
  495.     shl    ax,cl            ; ax := paragraph within memory block
  496.  
  497.     cmp    cs:mem_blk_table.typ[bx],em_flg ; Expanded Memory?
  498.     jnz    write_set_par
  499.     call    map_hdl_2_pages            ; - Yes, map EM
  500.  
  501. write_set_par:
  502.     add    ax,cs:mem_blk_table.par[bx] ; ax := paragraph in phy mem
  503.     mov    es,ax
  504.     xor    di,di            ; es:di := address of sector
  505.     
  506.     mov    cx,cs:mem_blk_table.siz[bx] ; cx := size of blk in sectors
  507.     pop    ax            ; ax := start sector within blk
  508.     sub    cx,ax            ; cx := secs remaining in mem blk
  509.  
  510. write_one_sector:
  511.     or    dx,dx            ; All sectors transfered?
  512.     jz    write_finish        ; -- Yes
  513.     dec    dx
  514.     push    cx            ; save sector counter
  515.     mov    cx,bytes_per_sec    ; 512 bytes per sector
  516.     rep    movsb            ; copy sector to buffer
  517.     pop    cx            ; cx := secs remaining in blk + 1
  518.     mov    ax,es
  519.     add    ax,par_per_sec        ; 32 paragraphs per sector
  520.     mov    es,ax
  521.     xor    di,di            ; es:di := address of next sector
  522.         mov    ax,ds            ; advance ds to next sector
  523.     add    ax,par_per_sec
  524.     mov    ds,ax
  525.     and    si,000fh        ; ds:si := normalized transfer address
  526.     loop    write_one_sector    ; if not end of block, do another
  527.     add    bx,size mem_blk_table_entry
  528.  
  529.     cmp    cs:mem_blk_table.typ[bx],em_flg ; Expanded Memory?
  530.     jnz    write_set_par_in_loop
  531.     call    map_hdl_2_pages            ; - Yes, map EM
  532.  
  533. write_set_par_in_loop:
  534.     mov    ax,cs:mem_blk_table.par[bx]
  535.     mov    es,ax            ; es:di := start of new memory block
  536.     mov    cx,cs:mem_blk_table.siz[bx] ; cx := size of new blk in secs
  537.     jmp    write_one_sector
  538.  
  539. write_finish:
  540.     call    restore_em_context    ; If needed, restore em context
  541.     mov    ax,s_done        ; ax := transfer done
  542.     ret
  543.  
  544. write    endp
  545.  
  546.  
  547. ; ---- Write and verify ----
  548.  
  549. write_verify    proc    near        ; normal write with read verify
  550.  
  551.     jmp    write            ; assume no errors
  552.  
  553. write_verify    endp
  554.  
  555.  
  556. ; ==== Support Functions ====
  557. ;
  558. ; ----    Map a handle of Expanded Memory to the Memory Block pages
  559.  
  560. ;    ENTRY:    BX = pointer to Memory Block Table entry (in CS)
  561. ;    EXIT:    Memory is mapped and paragraph address updated in entry.
  562. ;        Flag at CS:em_context_flg is set to nonzero to indicate that
  563. ;        expanded memory mapping context has been saved.  The handle
  564. ;        underwhich the context was saved is stored at
  565. ;        CS:em_context_hdl.
  566. ;    USES:    CX
  567.  
  568. map_hdl_2_pages    proc    near
  569.     push    ax
  570.     push    bx
  571.     push    dx
  572.     mov    dx,cs:mem_blk_table.hdl[bx]    ; get handle of mem blk
  573.     cmp    cs:em_context_flg,0        ; em context saved yet?
  574.     jnz    do_map
  575.     mov    ah,emm_sav_map            ; - No, then save it
  576.     int    usri_emm
  577.     mov    cs:em_context_hdl,dx        ; store handle underwhich saved
  578.     mov    cs:em_context_flg,1        ; flag as saved
  579. do_map:
  580.     push    bx
  581.     mov    ah,emm_get_PFseg        ; get page frame segment
  582.     int    usri_emm
  583.     mov    ax,bx
  584.     pop    bx
  585.     mov    cs:mem_blk_table.par[bx],ax    ; store page frame segment
  586.     mov    cx,em_pag_per_mem_blk        ; # of 16K EM pages to map
  587. map_log_2_phy:
  588.     mov    ah,emm_map_memory        ; map memory
  589.     mov    al,cl                ; physical page number
  590.     mov    bx,cx                ; logical page number
  591.     dec    al                ; adjust relative to 0
  592.     dec    bx                ; adjust relative to 0
  593.     int    usri_emm
  594.     loop    map_log_2_phy
  595.     pop    dx
  596.     pop    bx
  597.     pop    ax
  598.     ret
  599. map_hdl_2_pages    endp
  600.  
  601. ; ---- Restore expanded memory context, if needed. ---
  602. ;    USES:    AX,DX
  603.  
  604. restore_em_context    proc    near
  605.     cmp    cs:em_context_flg,0    ; was context saved?
  606.     jz    restore_em_context_xit    ; - No, then just exit
  607.     mov    ah,emm_res_map        ; - Yes, then restore it..
  608.     mov    dx,cs:em_context_hdl    ;   ..using this handle
  609.     int    usri_emm
  610.     mov    cs:em_context_flg,0    ; clear context flag
  611. restore_em_context_xit:
  612.     ret
  613. restore_em_context    endp
  614.  
  615. ; ---- Unimplemented functions ----
  616.  
  617. unimplemented    proc    near
  618.     mov    ax,e_command
  619.     ret
  620. unimplemented    endp
  621.  
  622. ioctl_read    equ    unimplemented    ; IOCTL read
  623. check_input    equ    unimplemented    ; non-destructive read/status
  624. input_status    equ    unimplemented    ; input status
  625. input_flush    equ    unimplemented    ; flush input buffers
  626. output_status    equ    unimplemented    ; output status
  627. output_flush    equ    unimplemented    ; flush output buffers
  628. ioctl_write    equ    unimplemented    ; IOCTL write
  629.  
  630. ; ==== Memory Disk Data Area ====
  631. ;
  632. ; Align to paragraph boundary for easy computation of the sector address
  633.  
  634. if (( $ - driver) mod 16 )
  635.     org    ( $ - driver) + (16 - (( $- driver) mod 16 ))
  636. endif
  637.  
  638. mdisk_data    equ    $        ; memory disk starts here
  639.  
  640. ; ---- Boot record for initialization ----
  641.  
  642. boot_record    db    3 dup ( 0 )    ; non-bootable (no jump instruction )
  643.         db    'AMDISK  '    ; identification
  644.  
  645. bpb:                    ; BIOS Parameter Block
  646. bytes_in_sector    dw    bytes_per_sec    ; bytes/sector
  647. bpb_sec_per_cl    db    sec_per_cl    ; sectors/cluster
  648. bpb_reserved    dw    1        ; reserved sectors
  649. bpb_fats    db    fats_per_disk    ; number of FAT's
  650. bpb_root    dw    128        ; directory entries in root
  651. bpb_total    dw    min_size_sec    ; total number of sectors
  652. bpb_media    db    1        ; media type byte ...
  653. mem_blk_cnt    equ    bpb_media    ; ...is used for number of mem blocks
  654. bpb_fat_size    dw    sec_per_fat    ; sectors/FAT
  655.  
  656.         dw    1        ; sectors/track
  657.         dw    1        ; number of heads
  658.         dw    0        ; hidden sectors
  659.  
  660. mem_blk_table    mem_blk_table_entry <nor_flg,,min_size_sec,0>  ; memory block table
  661. end_mem_blk_table equ    $+(size mem_blk_table)*(max_size_sec/sec_per_blk)
  662.  
  663. fat1        equ    boot_record + bytes_per_sec
  664. fat2        equ    fat1 + (bytes_per_sec*sec_per_fat)
  665. root_dir    equ    fat1+(fats_per_disk*sec_per_fat*bytes_per_sec)
  666. first_data_sec    equ    root_dir + (64*32)
  667.  
  668. ; ==== End of Memory Disk Device Driver ====
  669.  
  670. driver        endp
  671. cseg        ends
  672.         end
  673.  
  674.